"""
主窗口集成多进程仿真 - 使用指南

将worker_threads中的多线程替换为多进程，彻底消除GIL卡顿
"""

# ===============================================
# 步骤1: 修改 gui/main_window_pyqtads.py
# ===============================================

# 在文件顶部添加导入
from simulator.simulation_process import SimulationProcess

class MainWindow:
    def __init__(self):
        # ... 现有初始化代码 ...

        # ===== 替换点1: 使用进程而不是线程 =====
        # 旧代码：
        # self.thread_manager = WorkerThreadManager(...)

        # 新代码：
        self.sim_process = SimulationProcess(self.radar_engine)

    def setup_timer(self):
        """设置定时器用于从进程读取数据"""
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self.update_displays_from_process)
        # 可以保持10Hz，因为读取是非阻塞的
        self.update_interval = 100  # 10Hz

    def start_simulation(self):
        """启动仿真"""
        try:
            # 获取仿真时长
            duration = self.control_panel.get_simulation_duration()

            # ===== 替换点2: 启动进程而不是线程 =====
            # 旧代码：
            # self.thread_manager.start_continuous_simulation(duration)

            # 新代码：
            self.sim_process.start(duration=duration)

            # 启动界面更新定时器
            if not self.update_timer.isActive():
                self.update_timer.start(self.update_interval)

            self.statusBar().showMessage(f"仿真运行中... (时长: {duration}秒)")
            self.compact_status_bar.update_status("仿真运行中", 0)

        except Exception as e:
            self.show_error(f"启动仿真失败: {str(e)}")

    def update_displays_from_process(self):
        """
        从仿真进程读取数据并更新界面（非阻塞）

        关键优势：
        - 这个函数在主进程中运行，有独立的GIL
        - 仿真进程也有独立的GIL
        - 两个进程真正并行，互不阻塞
        """
        try:
            import time
            t_start = time.perf_counter()

            # ===== 核心：非阻塞读取 =====
            result = self.sim_process.get_latest_result()

            if not result:
                # 没有新数据，直接返回（不阻塞）
                return

            # 检查错误
            if 'error' in result:
                self.show_error(f"仿真错误: {result['error']}")
                self.stop_simulation()
                return

            # 更新状态栏
            sim_time = result.get('simulation_time', 0.0)
            self.compact_status_bar.update_simulation_time(sim_time)

            # 计算进度
            if hasattr(self, 'simulation_target_duration') and self.simulation_target_duration > 0:
                progress = min(int((sim_time / self.simulation_target_duration) * 100), 100)
            else:
                progress = 0

            self.compact_status_bar.update_status(
                f"仿真中 (总时长: {self.simulation_target_duration:.1f}s)",
                progress
            )

            # 更新雷达模式
            radar_mode = result.get('radar_mode', 'search')
            self.compact_status_bar.update_radar_mode(radar_mode)

            # ===== 智能更新信号显示（降低频率） =====
            signal_data = result.get('signal_data', {})
            if signal_data:
                # 限制信号更新频率为2Hz
                if not hasattr(self, '_last_signal_update_time'):
                    self._last_signal_update_time = 0

                current_time = time.time()
                if current_time - self._last_signal_update_time >= 0.5:
                    self._last_signal_update_time = current_time
                    self._update_signal_plots(signal_data)

            # 更新测量结果
            measurements = result.get('measurements', [])
            if measurements:
                targets_dict = self._prepare_target_data_for_display()
                self.measurement_widget.update_measurements(measurements, targets_dict)

            t_end = time.perf_counter()
            update_time = (t_end - t_start) * 1000

            # 性能监控
            if not hasattr(self, '_last_perf_print'):
                self._last_perf_print = 0
            if time.time() - self._last_perf_print >= 1.0:
                print(f"[主进程] 更新耗时: {update_time:.2f}ms (仿真进程独立运行，无阻塞)")
                self._last_perf_print = time.time()

        except Exception as e:
            print(f"界面更新失败: {e}")
            import traceback
            traceback.print_exc()

    def _update_signal_plots(self, signal_data):
        """更新信号图（从signal_data中提取并绘制）"""
        try:
            # 获取信号处理器
            signal_processor = self.get_signal_processor()

            # 提取信号数据
            tx_time = signal_data.get('tx_time', [])
            rx_time = signal_data.get('rx_time', [])
            tx_signal = signal_data.get('tx_signal', [])
            rx_signal = signal_data.get('rx_signal', [])
            compressed_signal = signal_data.get('compressed_signal', [])

            # 转换为相对时间
            import numpy as np
            tx_time_rel = tx_time - tx_time[0] if len(tx_time) > 0 else tx_time
            rx_time_rel = rx_time - rx_time[0] if len(rx_time) > 0 else rx_time

            if compressed_signal is not None and len(compressed_signal) > 0:
                t_pc = np.linspace(0, len(compressed_signal) / signal_processor.fs,
                                   len(compressed_signal))
                pc_time_rel = t_pc - t_pc[0] if len(t_pc) > 0 else t_pc
            else:
                pc_time_rel = tx_time_rel
                compressed_signal = np.zeros_like(tx_signal)

            # 绘制（现在是真正的非阻塞，因为没有GIL竞争）
            self.tx_signal_widget.plot_signal(tx_time_rel, tx_signal, 'complex')
            self.rx_signal_widget.plot_signal(rx_time_rel, rx_signal, 'complex')
            self.pc_signal_widget.plot_signal(pc_time_rel, compressed_signal, 'compressed')

        except Exception as e:
            print(f"信号绘图失败: {e}")

    def stop_simulation(self):
        """停止仿真"""
        try:
            # ===== 替换点3: 停止进程而不是线程 =====
            # 旧代码：
            # self.thread_manager.stop_continuous_simulation()

            # 新代码：
            self.sim_process.stop()

            # 停止界面更新定时器
            self.update_timer.stop()

            self.statusBar().showMessage("仿真已停止")
            self.compact_status_bar.update_status("仿真已停止", None)
            self.compact_status_bar.hide_simulation_time()

        except Exception as e:
            self.show_error(f"停止仿真失败: {str(e)}")

    def closeEvent(self, event):
        """窗口关闭事件"""
        # ... 现有代码 ...

        # ===== 替换点4: 确保进程正确退出 =====
        # 旧代码：
        # if hasattr(self, 'thread_manager'):
        #     self.thread_manager.stop_all_workers()

        # 新代码：
        if hasattr(self, 'sim_process'):
            self.sim_process.stop()

        event.accept()


# ===============================================
# 步骤2: 测试多进程性能
# ===============================================

def test_multiprocess_performance():
    """独立测试脚本，验证多进程性能"""
    import psutil
    import os

    print("=" * 70)
    print("多进程性能测试")
    print("=" * 70)

    # 创建仿真进程
    from simulator.sim_engine import SimEngine
    from simulator.simulation_process import SimulationProcess

    sim_process = SimulationProcess(SimEngine())

    # 启动仿真
    print("\n启动5秒仿真...")
    sim_process.start(duration=5.0)

    # 监控CPU使用率
    main_process = psutil.Process(os.getpid())
    print(f"\n主进程PID: {os.getpid()}")
    if sim_process.process:
        print(f"仿真进程PID: {sim_process.process.pid}")

    import time
    last_time = 0
    update_count = 0
    cpu_samples = []

    while sim_process.is_alive():
        # 读取结果
        result = sim_process.get_latest_result()
        if result:
            sim_time = result.get('simulation_time', 0)
            if sim_time > last_time:
                last_time = sim_time
                update_count += 1

                # 测量CPU使用率
                cpu_percent = main_process.cpu_percent()
                cpu_samples.append(cpu_percent)

                print(f"  t={sim_time:.2f}s | 主进程CPU: {cpu_percent:.1f}% | "
                      f"更新次数: {update_count}")

        # 模拟GUI工作
        time.sleep(0.1)

    # 停止
    sim_process.stop()

    # 统计
    print("\n" + "=" * 70)
    print("测试结果：")
    print(f"  总更新次数: {update_count}")
    if cpu_samples:
        print(f"  主进程平均CPU: {sum(cpu_samples)/len(cpu_samples):.1f}%")
    print("\n期望结果：")
    print("  ✓ CPU使用率应该在40-60% (双核心并行)")
    print("  ✓ 主进程始终响应，无阻塞")
    print("  ✓ 更新次数应该接近50次 (5秒 * 10Hz)")
    print("=" * 70)


# ===============================================
# 步骤3: 运行测试
# ===============================================

if __name__ == '__main__':
    # 运行性能测试
    test_multiprocess_performance()
